package com.realone.packman.codec.decoder;

import com.realone.packman.codec.decoder.vo.BmsDecoderDataVo;

import java.nio.ByteBuffer;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 接收蓝牙数据
 *
 * @author hugx
 * @create 2018-09-19 17:30
 */
public class ReceiverBluetoothData {

    private static ReceiverBluetoothData instance;

    private BmsDecoderCallbak bmsDecoderCallbak;

    /* 接收蓝牙数据队列 */
    private ConcurrentLinkedQueue<byte[]> reponseDataQueue = new ConcurrentLinkedQueue<byte[]>();

    private byte[] disposeDataLock = new byte[0]; //处理蓝牙数据的锁

    private ReceiverBluetoothData() {
        new Thread(new DisposeReponseDataTask(), "DisposeReponseDataTask  Thread ").start();
    }

    public static ReceiverBluetoothData getInstance() {
        if (instance == null) {
            synchronized (ReceiverBluetoothData.class) {
                instance = new ReceiverBluetoothData();
            }
        }

        return instance;
    }

    /**
     * 接收蓝牙数据
     *
     * @param reponseData
     */
    public void receiverData(byte[] reponseData) {
        reponseDataQueue.add(reponseData);
        synchronized (disposeDataLock) {
            disposeDataLock.notifyAll();
        }
    }


    public void setBmsDecoderCallbak(BmsDecoderCallbak bmsDecoderCallbak) {
        this.bmsDecoderCallbak = bmsDecoderCallbak;
    }


    /**
     * 处理蓝牙数据任务
     */
    private class DisposeReponseDataTask implements Runnable {

        private BmsDecoder<BmsDecoderDataVo> bmsDecoder = new BmsDecoder();

        private ByteBuffer bb = ByteBuffer.allocate(1024);
        private ByteBuffer bbErr = ByteBuffer.allocate(1024);

        private boolean startFlag = false; //开始接收头标志，true -开始从头接收数据
        private byte resDataLen = 0; //响应数据内容长度
        private boolean startReadResDataFlag = false; //开始读响应数据内容


        @Override
        public void run() {
            while (true) {
                disposeReponseData();
            }
        }

        /**
         * 根据协议过滤数据
         */
        private void disposeReponseData() {

            byte[] data = reponseDataQueue.poll();

            if (data == null || data.length == 0) {
                synchronized (disposeDataLock) {
                    try {
                        disposeDataLock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                return;
            }


            bbErr.put(data);
            for (int i = 0; i < data.length; i++) {

                if(!(data.length - 1 == i) && checkPackageHead(data[i], data[i + 1])) {
                    if(startFlag){
                        resetFlag();
                        bb.clear();
                        bb.put(data[i]);
                        startFlag=true;
                        continue;
                    }else {
                        startFlag = true;
                    }
                }

                if (startFlag) {
                    bb.put(data[i]);

                    /* 用于判断从startFlag 为true 后，再判断结束本包数据的接收 */
                    if (bb.position() == 6) {
                        resDataLen = data[i];
                        resDataLen += 7;
                        startReadResDataFlag = true;
                    }

                    if (startReadResDataFlag && (bb.position() == resDataLen)) {
                        resetFlag();
                        byte[] requestData = new byte[bb.position()];
                        bb.flip();
                        bb.get(requestData);
                        bb.clear();
                        decoder(requestData);
                        bbErr.clear();

                    }
                }
            }
        }



        private void resetFlag() {
            startFlag = false;
            startReadResDataFlag = false;
            resDataLen = 0;
        }

        /**
         * 判断是否是包头的开始
         *
         * @param before   帧前导码
         * @param dividing 帧分界符
         * @return
         */
        private boolean checkPackageHead(byte before, byte dividing) {

            if (before == 0x7e && dividing == 0x55) {
                return true;
            } else {
                return false;
            }

        }

        /**
         * 解码
         *
         * @param data
         */
        private void decoder(byte[] data) {
            try {
                BmsDecoderDataVo bmsDecoderDataVo = bmsDecoder.decoder(data);
                bmsDecoderCallbak.callBmsDecoder(bmsDecoderDataVo);
            }catch (Exception e){
                BmsDecoderDataVo bmsDecoderDataVo =new BmsDecoderDataVo(0xff);
                int len=bbErr.position();
                byte [] errData=new byte[len];
                bbErr.flip();
                bbErr.get(errData);
                bbErr.clear();
                bmsDecoderDataVo.setErrMsg(byte2hex(errData));
            }


        }

        /**
         * 字节数组转换为十六进制字符串
         *
         * @param b   byte[] 需要转换的字节数组
         * @return String 十六进制字符串
         */
        private    String byte2hex(byte b[]) {
            if (b == null) {
                throw new IllegalArgumentException(
                        "Argument b ( byte array ) is null! ");
            }
            StringBuilder sb = new StringBuilder();
            String stmp = "";
            for (int n = 0; n < b.length; n++) {
                stmp = Integer.toHexString(b[n] & 0xff);
                if (stmp.length() == 1) {
                    sb.append("0").append(stmp);
                } else {
                    sb.append(stmp);
                }
            }
            return sb.toString().toLowerCase();
        }
    }
}
